#include <string.h>

#include "gkt_board.h"
#include "gkt_debug.h"
#include "gkt_date_time.h"
#include "gkt_keypad.h"
#include "gkt_rtc.h"
#include "gkt_adc.h"
#include "gkt_user.h"
#include "gkt_door.h"
#include "gkt_rfid.h"
#include "gkt_card.h"
#include "gkt_fpsensor.h"
#include "gkt_wakeup.h"
#include "gkt_factory_reset.h"
#include "gkt_battery.h"
#include "window_common.h"
#include "window_verify.h"
#include "window_opcode.h"
#include "window_factory_inspect.h"
#include "gkt_os.h"
#include "window_hotkey.h"
#include "gkt_gpio.h"

#ifdef GKT_CONFIG_WINDOW_WELCOME_VERIFY_DISCARD_1ST_DIGIT_KEY
#define WINDOW_WELCOME_VERIFY_DISCARD_1ST_DIGIT_KEY	\
	GKT_CONFIG_WINDOW_WELCOME_VERIFY_DISCARD_1ST_DIGIT_KEY
#else
#define WINDOW_WELCOME_VERIFY_DISCARD_1ST_DIGIT_KEY	0
#endif

#define WINDOW_WELCOME_TIME_RESHOW_TIMEOUT	3000

enum {
	WIDGET_ID_DATE = 0,
	WIDGET_ID_BATTERY_LEVEL,
	WIDGET_ID_TIME,
	WIDGET_ID_BATTERY_LOW,
	WIDGET_ID_VENDOR_TEXT,
#if WINDOW_VENDOR_IMAGE_ENABLE
	WIDGET_ID_VENDOR_IMAGE,
#endif
	WIDGET_ID_MAX
};

enum {
	TIMER_ID_DATE_TIME_UPDATE = 0,
	TIMER_ID_TIME_RESHOW,
	TIMER_ID_FACTORY_RESET_CHECK,
#if defined(GKT_CONFIG_RFID_ENABLE) && GKT_CONFIG_RFID_ENABLE
	TIMER_ID_CARD_DELAY_ENABLE,
#endif
#if defined(GKT_CONFIG_DOOR_TAMPER_ENABLE) && GKT_CONFIG_DOOR_TAMPER_ENABLE
	TIMER_ID_DOOR_TAMPER_CHECK,
#endif
#if defined(GKT_CONFIG_INTERNAL_DOORBELL_ENABLE) && GKT_CONFIG_INTERNAL_DOORBELL_ENABLE
	TIMER_ID_INTERNAL_DOORBELL_DELAY,
#endif
	TIMER_ID_MAX
};

#ifdef GKT_CONFIG_FACTORY_RESET_ACTIVE_TIME
#define FACTORY_RESET_ACTIVE_TIME	GKT_CONFIG_FACTORY_RESET_ACTIVE_TIME
#else
#define FACTORY_RESET_ACTIVE_TIME	5000
#endif
#define FACTORY_RESET_CHECK_UNIT	200
#define FACTORY_RESET_CHECK_COUNTER	(FACTORY_RESET_ACTIVE_TIME / FACTORY_RESET_CHECK_UNIT)
#define FACTORY_RESET_CHECK_COUNTER_1S	(1000 / FACTORY_RESET_CHECK_UNIT)

#define DOOR_TAMPER_ACTIVE_TIME	500
#define DOOR_TAMPER_CHECK_UNIT	100
#define DOOR_TAMPER_CHECK_COUNTER	(DOOR_TAMPER_ACTIVE_TIME / DOOR_TAMPER_CHECK_UNIT)

/* voice type */
enum {
	WINDOW_WELCOME_VOICE_WELCOME = 0,
	WINDOW_WELCOME_VOICE_DOOR_BELL,
	WINDOW_WELCOME_VOICE_BATTERY_LOW,
#if defined(GKT_CONFIG_DOOR_MAGNETIC_ENABLE) && GKT_CONFIG_DOOR_MAGNETIC_ENABLE
	WINDOW_WELCOME_VOICE_DOOR_NOT_CLOSED,
#endif
#if defined(GKT_CONFIG_DOOR_TAMPER_ENABLE) && GKT_CONFIG_DOOR_TAMPER_ENABLE
	WINDOW_WELCOME_VOICE_DOOR_TEMPER,
#endif
#if defined(GKT_CONFIG_FACTORY_INSPECT_ENABLE) && GKT_CONFIG_FACTORY_INSPECT_ENABLE
	WINDOW_WELCOME_VOICE_FACTORY_INSPECT_INCOMPLETE,
#endif
	WINDOW_WELCOME_VOICE_MAX
};

enum {
	WINDOW_WELCOME_MASK_DEFAULT = 0,
	WINDOW_WELCOME_MASK_BATTERY_LOW,
	WINDOW_WELCOME_MASK_DOOR_TAMPER,
	WINDOW_WELCOME_MASK_MAX
};

enum {
	WINDOW_WELCOME_SHOW_NORMAL = 0,
	WINDOW_WELCOME_SHOW_BATTERY_LOW,
	WINDOW_WELCOME_SHOW_MAX
};

#define WINDOW_WELCOME_DATE_TEXT_MAXSIZE	12
#define WINDOW_WELCOME_TIME_TEXT_MAXSIZE	10

GKT_WINDOW_WIDGET_DESCS_DEFINE(welcome) = {
	[WIDGET_ID_DATE] = GKT_WIDGET_LABEL_DESC(
		GKT_WIDGET_F_ALIGN_LEFT | GKT_WIDGET_F_ALIGN_CENTER,
		WINDOW_FONT_NORMAL_SIZE, 
		GKT_COLOR_WHITE, GKT_COLOR_BLACK,
		4, 0, 80, WINDOW_WIDGET_NORMAL_HEIGHT,
		"2022-01-01"),
	[WIDGET_ID_BATTERY_LEVEL] = GKT_WIDGET_IMAGE_DESC(
		GKT_WIDGET_F_ALIGN_RIGHT | GKT_WIDGET_F_ALIGN_CENTER,
		GKT_COLOR_WHITE, GKT_COLOR_BLACK,
		GKT_SCREEN_WIDTH - 24, 0, 
		20, WINDOW_WIDGET_NORMAL_HEIGHT,
		WINDOW_IMAGE_battery_full),
	[WIDGET_ID_TIME] = GKT_WIDGET_LABEL_DESC(
		GKT_WIDGET_F_ALIGN_MIDDLE | GKT_WIDGET_F_ALIGN_CENTER,
		28, 
		GKT_COLOR_WHITE, GKT_COLOR_BLACK,
		0, WINDOW_WIDGET_NORMAL_HEIGHT, 
		GKT_SCREEN_WIDTH, WINDOW_WIDGET_NORMAL_HEIGHT * 2,
		"00:00:00"),
	[WIDGET_ID_BATTERY_LOW] = GKT_WIDGET_LABEL_DESC(
		GKT_WIDGET_F_ALIGN_MIDDLE | GKT_WIDGET_F_ALIGN_CENTER,
		20, 
		GKT_COLOR_RED, GKT_COLOR_BLACK,
		0, WINDOW_WIDGET_NORMAL_HEIGHT, 
		GKT_SCREEN_WIDTH, WINDOW_WIDGET_NORMAL_HEIGHT * 2,
		WINDOW_TEXT_ID_battery_low_power),
	[WIDGET_ID_VENDOR_TEXT] = GKT_WIDGET_LABEL_DESC(
		GKT_WIDGET_F_ALIGN_MIDDLE | GKT_WIDGET_F_ALIGN_CENTER,
		WINDOW_FONT_NORMAL_SIZE, 
		GKT_COLOR_WHITE, GKT_COLOR_BLACK,
		(GKT_SCREEN_WIDTH-WINDOW_FONT_NORMAL_SIZE*4)/2,
		WINDOW_WIDGET_NORMAL_HEIGHT * 3, 
		64, WINDOW_WIDGET_NORMAL_HEIGHT,
		WINDOW_TEXT_ID_vendor),	
#if WINDOW_VENDOR_IMAGE_ENABLE
	[WIDGET_ID_VENDOR_IMAGE] = GKT_WIDGET_IMAGE_DESC(
		GKT_WIDGET_F_ALIGN_MIDDLE,
		GKT_COLOR_WHITE, GKT_COLOR_BLACK,
		(GKT_SCREEN_WIDTH - WINDOW_VENDOR_IMAGE_MAX_WIDTH) / 2, 
		(GKT_SCREEN_HEIGHT - WINDOW_VENDOR_IMAGE_MAX_HEIGHT),
		WINDOW_VENDOR_IMAGE_MAX_WIDTH, WINDOW_VENDOR_IMAGE_MAX_HEIGHT,
		NULL),
#endif
};

typedef struct _window_welcome {
	gkt_wakeup_src_e	wakeup_resource;

	uint32_t	show_type;

	uint32_t	voice_playing_id;
	uint32_t 	door_bell_number;
	int	voice_request_ids[WINDOW_WELCOME_VOICE_MAX];

	gkt_battery_level_e	battery_level;
	int	battery_low_showed;

#if defined(GKT_CONFIG_FACTORY_INSPECT_ENABLE) && GKT_CONFIG_FACTORY_INSPECT_ENABLE
	int	factory_inspect_complete;
#endif

#if defined(GKT_CONFIG_RFID_ENABLE) && GKT_CONFIG_RFID_ENABLE
	gkt_card_info_s	card_info;
#if defined(GKT_CONFIG_CARD_HEADER_ENABLE) && GKT_CONFIG_CARD_HEADER_ENABLE
	uint8_t card_header[16];
#endif
#endif

#if WINDOW_VENDOR_IMAGE_ENABLE
	gkt_image_attr_s vendor_image;
#endif

#if defined(GKT_CONFIG_DOOR_TAMPER_ENABLE) && GKT_CONFIG_DOOR_TAMPER_ENABLE
	uint32_t	door_tamper_poll_counter;
#endif

	int	factory_reset_detect;
	int	factory_reset_check_complete;
	int factory_reset_check_complete_voice_id;
	uint32_t	factory_reset_poll_counter;

	window_verify_attr_u	verify_attr;

	gkt_date_time_s	dt;
	char	date_text[WINDOW_WELCOME_DATE_TEXT_MAXSIZE];	/* 2019-12-31 */
	char	time_text[WINDOW_WELCOME_TIME_TEXT_MAXSIZE];	/* 12:23:45 */
} window_welcome_s;
static window_welcome_s s_window_welcome;

static void window_welcome_mask(uint32_t mask_status)
{
	uint32_t mask_bit = 0;

	if(mask_status == WINDOW_WELCOME_MASK_DEFAULT) {
#if defined(GKT_CONFIG_RFID_ENABLE) && GKT_CONFIG_RFID_ENABLE
		if (g_window_ram_data.delay_unmask_card) {
			mask_bit |= 1U << GKT_EVENT_CARD;
			g_window_ram_data.delay_unmask_card_ms = 
					gkt_systime_ms() + WINDOW_DATA_DELAY_UNMASK_CARD_TIME + 100;
			gkt_window_timer_set(TIMER_ID_CARD_DELAY_ENABLE, 
					WINDOW_DATA_DELAY_UNMASK_CARD_TIME, 0, 0);
		}
#endif
		window_common_mask(mask_bit);
	}
	else if((mask_status == WINDOW_WELCOME_MASK_BATTERY_LOW)
		|| (mask_status == WINDOW_WELCOME_MASK_DOOR_TAMPER)) 
	{
		window_common_mask_all();
	}

#if !defined(GKT_CONFIG_WINDOW_VOICE_MUTE_DISABLE) \
	|| !GKT_CONFIG_WINDOW_VOICE_MUTE_DISABLE
	if (gp_window_data->voice_mute_enable)
		mask_bit = ~0;
	else
#endif
		mask_bit = (1U << GKT_KEY_ASTERISK) | (1U << GKT_KEY_BELL);
	gkt_key_voice_mask(mask_bit);
}

#if WINDOW_VENDOR_IMAGE_ENABLE
static void window_welcome_update_vendor(void)
{
	const window_vendor_image_s *c_vendor_image;

	if (!s_window_welcome.vendor_image.data) {
		c_vendor_image = window_vendor_get_image();
		if (c_vendor_image) {
			s_window_welcome.vendor_image.width = c_vendor_image->width;
			s_window_welcome.vendor_image.height = c_vendor_image->height;
			s_window_welcome.vendor_image.data = &c_vendor_image->data[0];

			gkt_trace("window_welcome: vendor image - %u @ %u\n",
						s_window_welcome.vendor_image.width,
						s_window_welcome.vendor_image.height);

			gkt_widget_set_showable_by_id(WIDGET_ID_VENDOR_TEXT, 0);
			gkt_widget_set_showable_by_id(WIDGET_ID_VENDOR_IMAGE, 1);
			gkt_widget_set_data_by_id(WIDGET_ID_VENDOR_IMAGE, 
					(uint32_t)&s_window_welcome.vendor_image);

			if (gkt_window_current_is_showed()) {
				if (gkt_widget_is_showed_by_id(WIDGET_ID_VENDOR_TEXT))
					gkt_widget_hide_by_id(WIDGET_ID_VENDOR_TEXT);
				gkt_widget_show_by_id(WIDGET_ID_VENDOR_IMAGE);
			}
		}
		else {
			s_window_welcome.vendor_image.data = NULL;

			gkt_widget_set_showable_by_id(WIDGET_ID_VENDOR_TEXT, 1);
			gkt_widget_set_showable_by_id(WIDGET_ID_VENDOR_IMAGE, 0);

			if (gkt_window_current_is_showed()) {
				if (gkt_widget_is_showed_by_id(WIDGET_ID_VENDOR_IMAGE))
					gkt_widget_hide_by_id(WIDGET_ID_VENDOR_IMAGE);
				gkt_widget_show_by_id(WIDGET_ID_VENDOR_TEXT);
			}
		}
	}
}
#else
#define window_welcome_update_vendor()	do {} while(0)
#endif

static const uint32_t sc_window_welcome_battery_images[GKT_BATTERY_LEVEL_MAX] = {
	WINDOW_IMAGE_battery_empty,
	WINDOW_IMAGE_battery_25,
	WINDOW_IMAGE_battery_50,
	WINDOW_IMAGE_battery_75,
	WINDOW_IMAGE_battery_full
};
static void window_welcome_get_battery_level(void)
{
	gkt_battery_set_adc_adjust_value(gp_window_unreset_data->adc_adjust_value);
	s_window_welcome.battery_level = gkt_battery_get_level();
	gkt_trace("window_welcome: battery_level = %u\n", 
			s_window_welcome.battery_level);
}
static void window_welcome_update_battery(void)
{
	if (s_window_welcome.battery_level >= GKT_BATTERY_LEVEL_MAX)
		s_window_welcome.battery_level = GKT_BATTERY_LEVEL_FULL;
	else if (GKT_BATTERY_LEVEL_EMPTY == s_window_welcome.battery_level) {
		gkt_widget_set_color_by_id(WIDGET_ID_BATTERY_LEVEL, 
				GKT_COLOR_RED, GKT_COLOR_BLACK);
	}
	else if (GKT_BATTERY_LEVEL_25 == s_window_welcome.battery_level) {
		gkt_widget_set_color_by_id(WIDGET_ID_BATTERY_LEVEL, 
				GKT_COLOR_ORANGE, GKT_COLOR_BLACK);
	}

	gkt_widget_set_data_by_id(WIDGET_ID_BATTERY_LEVEL,
		sc_window_welcome_battery_images[s_window_welcome.battery_level]);
}

static void window_welcome_date_time_init(void)
{
	int retval;

	retval = gkt_rtc_get_time(&s_window_welcome.dt);
	if (retval != GKT_SUCCESS) {
		s_window_welcome.dt.date.year = GKT_DT_YEAR_BASE;
		s_window_welcome.dt.date.month = GKT_DT_MONTH_JAN;
		s_window_welcome.dt.date.day = 1;
		s_window_welcome.dt.time.u32_value = 0;
	}

	gkt_window_timer_set(TIMER_ID_DATE_TIME_UPDATE, 
			1000, GKT_WINDOW_TIMER_F_PERIODIC, 0);
}

static void window_welcome_update_date(void)
{
	s_window_welcome.date_text[0] = '0' + (s_window_welcome.dt.date.year / 1000);
	s_window_welcome.date_text[1] = '0' + (s_window_welcome.dt.date.year / 100) % 10;
	s_window_welcome.date_text[2] = '0' + (s_window_welcome.dt.date.year % 100) / 10;
	s_window_welcome.date_text[3] = '0' + (s_window_welcome.dt.date.year % 10);
	s_window_welcome.date_text[4] = '-';
	s_window_welcome.date_text[5] = '0' + (s_window_welcome.dt.date.month / 10);
	s_window_welcome.date_text[6] = '0' + (s_window_welcome.dt.date.month % 10);
	s_window_welcome.date_text[7] = '-';
	s_window_welcome.date_text[8] = '0' + (s_window_welcome.dt.date.day / 10);
	s_window_welcome.date_text[9] = '0' + (s_window_welcome.dt.date.day % 10);
	s_window_welcome.date_text[10] = '\0';

	gkt_widget_set_data_by_id(WIDGET_ID_DATE, 
			(uint32_t)s_window_welcome.date_text);
}

static void window_welcome_update_time(void)
{
	s_window_welcome.time_text[0] = '0' + (s_window_welcome.dt.time.hour / 10);
	s_window_welcome.time_text[1] = '0' + (s_window_welcome.dt.time.hour % 10);
	s_window_welcome.time_text[2] = ':';
	s_window_welcome.time_text[3] = '0' + (s_window_welcome.dt.time.minute / 10);
	s_window_welcome.time_text[4] = '0' + (s_window_welcome.dt.time.minute % 10);
	s_window_welcome.time_text[5] = ':';
	s_window_welcome.time_text[6] = '0' + (s_window_welcome.dt.time.second / 10);
	s_window_welcome.time_text[7] = '0' + (s_window_welcome.dt.time.second % 10);
	s_window_welcome.time_text[8] = '\0';
	gkt_widget_set_data_by_id(WIDGET_ID_TIME, 
			(uint32_t)s_window_welcome.time_text);
}

static void window_welcome_show(uint32_t show_type)
{
	window_welcome_update_date();
	window_welcome_update_battery();
	window_welcome_update_vendor();

	gkt_trace("welcome: show %u --> %u ...\n", 
		s_window_welcome.show_type, show_type);
	if (WINDOW_WELCOME_SHOW_NORMAL == show_type) {
		gkt_widget_set_showable_by_id(WIDGET_ID_BATTERY_LOW, 0);
		gkt_widget_hide_by_id(WIDGET_ID_BATTERY_LOW);

		window_welcome_update_time();
		gkt_widget_set_showable_by_id(WIDGET_ID_TIME, 1);
		gkt_widget_show_by_id(WIDGET_ID_TIME);
	}
	else if (WINDOW_WELCOME_SHOW_BATTERY_LOW == show_type) {
		s_window_welcome.battery_low_showed = 1;

		gkt_window_timer_set(TIMER_ID_TIME_RESHOW, 
				WINDOW_WELCOME_TIME_RESHOW_TIMEOUT, 0, 0);

		gkt_widget_set_showable_by_id(WIDGET_ID_TIME,0);
		gkt_widget_hide_by_id(WIDGET_ID_TIME);

		gkt_widget_set_showable_by_id(WIDGET_ID_BATTERY_LOW, 1);
		gkt_widget_show_by_id(WIDGET_ID_BATTERY_LOW);
	}
	else {
		gkt_error("welcome_show: unknown type(%u)\n", 
				s_window_welcome.show_type);
		return;
	}

	s_window_welcome.show_type = show_type;
}

/************************************************************
 * welcome voice
 ************************************************************/
typedef struct _window_welcome_voice_attr {
	uint32_t	combind_id;
	uint32_t	flags;
	gkt_voice_output_playback_attr_s	params;
} window_welcome_voice_attr_s;
static const window_welcome_voice_attr_s 
	sc_window_welcome_voice_attrs[WINDOW_WELCOME_VOICE_MAX] = 
{
	[WINDOW_WELCOME_VOICE_WELCOME] = {
		.combind_id	= WINDOW_VOICE_COMBINED_ID(welcome_home),
		.flags	= GKT_WINDOW_VOICE_F_MUTE_AFFECTED,
		.params	= {
			.times	= 1,
			.interval	= 0,
		}
	},
	[WINDOW_WELCOME_VOICE_DOOR_BELL] = {
		.combind_id	= WINDOW_VOICE_COMBINED_ID(door_bell),
		.flags	= 0,
		.params	= {
			.times	= 1,//2
			.interval	= 0,//200
		}
	},
	[WINDOW_WELCOME_VOICE_BATTERY_LOW] = {
		.combind_id	= WINDOW_VOICE_COMBINED_ID(lowpower),
		.flags	= GKT_WINDOW_VOICE_F_UNINTERRUPT,
		.params	= {
			.times	= 1,
			.interval	= 0,
		}
	},
#if defined(GKT_CONFIG_DOOR_MAGNETIC_ENABLE) && GKT_CONFIG_DOOR_MAGNETIC_ENABLE
	[WINDOW_WELCOME_VOICE_DOOR_NOT_CLOSED] = {
		.combind_id	= WINDOW_VOICE_COMBINED_ID(door_not_closed),
		.flags	= GKT_WINDOW_VOICE_F_FOLLOWING | GKT_WINDOW_VOICE_F_AUTO_RESTART,
		.params	= {
			.times	= ~0,
			.interval	= 3000,
		}
	},
#endif
#if defined(GKT_CONFIG_DOOR_TAMPER_ENABLE) && GKT_CONFIG_DOOR_TAMPER_ENABLE
	[WINDOW_WELCOME_VOICE_DOOR_TEMPER] = {
		.combind_id	= WINDOW_VOICE_COMBINED_ID(alarm),
		.flags	= GKT_WINDOW_VOICE_F_DETACHED | GKT_WINDOW_VOICE_F_RESIDENT 
					| GKT_WINDOW_VOICE_F_FOLLOWING | GKT_WINDOW_VOICE_F_AUTO_RESTART,
		.params	= {
			.times	= ~0,
			.interval	= 1000,
		}
	},
#endif
#if defined(GKT_CONFIG_FACTORY_INSPECT_ENABLE) && GKT_CONFIG_FACTORY_INSPECT_ENABLE
	[WINDOW_WELCOME_VOICE_FACTORY_INSPECT_INCOMPLETE] = {
		.combind_id	= WINDOW_VOICE_COMBINED_ID(forbid),
		.flags	= GKT_WINDOW_VOICE_F_FOLLOWING | GKT_WINDOW_VOICE_F_AUTO_RESTART,
		.params	= {
			.times	= ~0,
			.interval	= 500,
		}
	},
#endif
};
static void window_welcome_play_voice(uint32_t id)
{
	const window_welcome_voice_attr_s *voice_attr;
	uint32_t flags;
	int retval;

	gkt_trace("window_welcome: play voice %u\n", id);

	if (id < WINDOW_WELCOME_VOICE_MAX) {
		if (s_window_welcome.voice_request_ids[id] > 0) {
			gkt_window_voice_stop_id(s_window_welcome.voice_request_ids[id]);
			s_window_welcome.voice_request_ids[id] = -1;
		}

		voice_attr = &sc_window_welcome_voice_attrs[id];
		flags = voice_attr->flags;
		flags |= GKT_WINDOW_VOICE_F_NOTIFY_START | GKT_WINDOW_VOICE_F_NOTIFY_END;
		retval = gkt_window_voice_play(&s_window_welcome.voice_request_ids[id], 
						voice_attr->combind_id, flags, &voice_attr->params);
		if (GKT_WINDOW_VOICE_ST_PLAYING == retval) {
			s_window_welcome.voice_playing_id = id;
			gkt_trace("window_welcome: voice (%d) playing ...\n", 
				s_window_welcome.voice_request_ids[id]);
		}
		else if (GKT_WINDOW_VOICE_ST_PENDING == retval) {
			gkt_info("window_welcome: voice (%d) pending ...\n", 
				s_window_welcome.voice_request_ids[id]);
		}
		else if (retval < 0) {
			s_window_welcome.voice_request_ids[id] = -1;
			gkt_info("window_welcome: voice failed %d\n", retval); 
		}
	}
}
static void window_welcome_stop_voice(uint32_t id)
{
	gkt_trace("window_welcome: stop voice %u\n", id);

	if (id < WINDOW_WELCOME_VOICE_MAX) {
		if (s_window_welcome.voice_playing_id == id)
			s_window_welcome.voice_playing_id = WINDOW_WELCOME_VOICE_MAX;

		if (s_window_welcome.voice_request_ids[id] > 0) {
			gkt_window_voice_stop_id(s_window_welcome.voice_request_ids[id]);
			s_window_welcome.voice_request_ids[id] = -1;
		}
	}
}
static void window_welcome_handle_voice_event(uint32_t minor_type, 
				int request_id)
{
	uint32_t voice_id;

	gkt_trace("window_welcome: voice - type(%u), request_id(%d)\n", 
		minor_type, request_id);

	for (voice_id = 0; voice_id < WINDOW_WELCOME_VOICE_MAX; voice_id++) {
		if ((s_window_welcome.voice_request_ids[voice_id] > 0)
			&& request_id == s_window_welcome.voice_request_ids[voice_id])
		{
			break;
		}
	}

	if (voice_id < WINDOW_WELCOME_VOICE_MAX) {
		if (GKT_WINDOW_VOICE_EVENT_PLAY_START == minor_type) {
			gkt_trace("window_welcome: voice(%u) start ...\n", voice_id);
			s_window_welcome.voice_playing_id = voice_id;
			return;
		}

		gkt_trace("window_welcome:voice(%u) end.\n", voice_id);

		if (WINDOW_WELCOME_VOICE_DOOR_BELL == voice_id) {
			if (!s_window_welcome.door_bell_number) {
				s_window_welcome.door_bell_number++;
#if defined(GKT_CONFIG_INTERNAL_DOORBELL_ENABLE) && GKT_CONFIG_INTERNAL_DOORBELL_ENABLE
				gkt_gpio_config(GKT_CONFIG_INTERNAL_DOORBELL_GPIO_PIN, GKT_GPIO_F_OUTPUT | GKT_GPIO_F_PULL_UP, NULL);
				gkt_gpio_set_pin_level(GKT_CONFIG_INTERNAL_DOORBELL_GPIO_PIN, 1);
				gkt_window_timer_set(TIMER_ID_INTERNAL_DOORBELL_DELAY, GKT_CONFIG_INTERNAL_DOORBELL_RESET_TIME_MS, 0, 0);
#endif
				window_welcome_play_voice(voice_id);
				return;
			}
		}
		
		s_window_welcome.voice_request_ids[voice_id] = -1;
		if (s_window_welcome.voice_playing_id == voice_id)
			s_window_welcome.voice_playing_id = WINDOW_WELCOME_VOICE_MAX;

		if (WINDOW_WELCOME_SHOW_BATTERY_LOW == s_window_welcome.show_type) {
			if (WINDOW_WELCOME_VOICE_BATTERY_LOW == voice_id) {
				gkt_window_timer_clear(TIMER_ID_TIME_RESHOW);
				window_welcome_mask(WINDOW_WELCOME_MASK_DEFAULT);
				window_welcome_show(WINDOW_WELCOME_SHOW_NORMAL);
			}
			else {
				/* reset TIME_RESHOW */
				gkt_window_timer_set(TIMER_ID_TIME_RESHOW, 
						WINDOW_WELCOME_TIME_RESHOW_TIMEOUT, 0, 0);
				window_welcome_play_voice(WINDOW_WELCOME_VOICE_BATTERY_LOW);
				return;
			}
		}

#if defined(GKT_CONFIG_FACTORY_INSPECT_ENABLE) && GKT_CONFIG_FACTORY_INSPECT_ENABLE
		if (!s_window_welcome.factory_inspect_complete)
			window_welcome_play_voice(WINDOW_WELCOME_VOICE_FACTORY_INSPECT_INCOMPLETE);
#endif
	}
}

#if defined(GKT_CONFIG_FACTORY_INSPECT_ENABLE) && GKT_CONFIG_FACTORY_INSPECT_ENABLE
static void window_welcome_check_factory_inspect_complete(void)
{
	gkt_user_amount_s amount;

	s_window_welcome.factory_inspect_complete = 1;
	if (!gp_window_unreset_data->factory_inspect_complete) {
		amount.used_nums = 0;
		gkt_user_get_amount(&amount,GKT_USER_AUTH_ADMIN, GKT_USER_TYPE_MAX);
		if (!amount.used_nums)
			s_window_welcome.factory_inspect_complete = 0;
	}

	gkt_trace("window_welcome: factory_inspect_complete(%d)\n", 
		s_window_welcome.factory_inspect_complete);
}
#else
#define window_welcome_check_factory_inspect_complete()	do {} while(0)
#endif

static void window_welcome_enter_verify_window(
				uint32_t user_type, uint32_t data)
{
	gkt_user_amount_s amount;

	s_window_welcome.verify_attr.type = WINDOW_VERIFY_TYPE_UNLOCK;
	s_window_welcome.verify_attr.unlock.user_type = user_type;
	s_window_welcome.verify_attr.unlock.extend_data = data;
	
#if defined(GKT_CONFIG_RFID_ENABLE) && GKT_CONFIG_RFID_ENABLE
	if (GKT_USER_TYPE_CARD == user_type) {
		uint32_t *event_data;
		int key_masked;

		event_data = (uint32_t *)data;
		gkt_card_info_s *card_info = (gkt_card_info_s *)event_data[0];
	
		memcpy(&s_window_welcome.card_info.base, &card_info->base, sizeof(gkt_rfid_info_s));
		s_window_welcome.card_info.header = NULL;
#if defined(GKT_CONFIG_CARD_HEADER_ENABLE) && GKT_CONFIG_CARD_HEADER_ENABLE
		memcpy(s_window_welcome.card_header, card_info->header, 16);
		s_window_welcome.card_info.header = s_window_welcome.card_header;
#endif	

		key_masked = gkt_event_is_masked(GKT_EVENT_KEY);
		if (!key_masked)
			gkt_event_mask_single(GKT_EVENT_KEY, GKT_KEY_MASK_F_LED_DETACH);

		amount.used_nums = 0;
		gkt_user_get_amount(&amount, GKT_USER_AUTH_ADMIN, GKT_USER_TYPE_MAX);
		if (!amount.used_nums) {
			g_window_ram_data.delay_unmask_card = 0;
			g_window_ram_data.delay_unmask_card_ms = 0;

#if WINDOW_VENDOR_IMAGE_ENABLE
			int retval = window_vendor_update_image(&s_window_welcome.card_info.base);
			if (GKT_SUCCESS == retval) {
				g_window_ram_data.delay_unmask_card = 1;
				gkt_event_mask_single(GKT_EVENT_CARD, 0);

				if (!key_masked) {
					gkt_thread_sleep(100);
					gkt_event_unmask_single(GKT_EVENT_KEY);
				}

				s_window_welcome.vendor_image.data = NULL;
				window_welcome_update_vendor();
				gkt_window_voice_play(NULL, WINDOW_VOICE_COMBINED_ID(key), 0, NULL);

				g_window_ram_data.delay_unmask_card_ms = 
						gkt_systime_ms() + WINDOW_DATA_DELAY_UNMASK_CARD_TIME + 100;
				gkt_window_timer_set(TIMER_ID_CARD_DELAY_ENABLE, 
						WINDOW_DATA_DELAY_UNMASK_CARD_TIME, 0, 0);

				return;
			}
#endif

			uint32_t describe;
			describe = gkt_card_describe_fetch(&s_window_welcome.card_info.base);
			gkt_trace("window_welcome: describe = %u\n", describe);
			if (describe) {
				if (WINDOW_OPCODE_COMPATIBLE_SYSTEM_INFO == describe)
					gkt_window_show(WINDOW_ID_sysinfo, 0);
				else if (WINDOW_OPCODE_COMPATIBLE_FACTORY_INSPECT_NBC == describe \
						|| WINDOW_OPCODE_COMPATIBLE_FACTORY_INSPECT_BC == describe)
				{
					gkt_window_show(WINDOW_ID_factory_inspect, describe);
				}
				else if (WINDOW_OPCODE_COMPATIBLE_AGING_TEST == describe)
					gkt_window_show(WINDOW_ID_aging_test, WINDOW_AGING_TEST_F_CARD_TRIGGER);
#ifdef GKT_CONFIG_KEYPAD_SENSITIVE_STANDBY_DELTA_ATTR_TABLE				
				else if (WINDOW_OPCODE_COMPATIBLE_KEYPAD_PARAMETER_STANDARD == describe) {
					if ((gp_window_unreset_data->keypad_parameter_value == GKT_KEYPAD_RESPONSE_SENSITIVITY)
						|| (gp_window_unreset_data->keypad_parameter_value == 0)) {
						g_window_ram_data.delay_unmask_card = 1;
						gkt_event_mask_single(GKT_EVENT_CARD, 0);
		
						if (!key_masked) {
							gkt_thread_sleep(100);
							gkt_event_unmask_single(GKT_EVENT_KEY);
						}

						gp_window_unreset_data->keypad_parameter_value = GKT_KEYPAD_RESPONSE_STANDARD;
						gkt_key_parameter_update(GKT_KEYPAD_RESPONSE_STANDARD);
						window_data_save();
						gkt_window_voice_play(NULL, WINDOW_VOICE_COMBINED_ID(set_success), 0, NULL);

						g_window_ram_data.delay_unmask_card_ms = 
						gkt_systime_ms() + 1000 + 100;
						gkt_window_timer_set(TIMER_ID_CARD_DELAY_ENABLE, 
							1000, 0, 0);
					}
				}
				else if (WINDOW_OPCODE_COMPATIBLE_KEYPAD_PARAMETER_SENSITIVE == describe) {
					if (gp_window_unreset_data->keypad_parameter_value != GKT_KEYPAD_RESPONSE_SENSITIVITY) {
						g_window_ram_data.delay_unmask_card = 1;
						gkt_event_mask_single(GKT_EVENT_CARD, 0);
		
						if (!key_masked) {
							gkt_thread_sleep(100);
							gkt_event_unmask_single(GKT_EVENT_KEY);
						}
						
						gp_window_unreset_data->keypad_parameter_value = GKT_KEYPAD_RESPONSE_SENSITIVITY;
						gkt_key_parameter_update(GKT_KEYPAD_RESPONSE_SENSITIVITY);
						window_data_save();

						gkt_window_voice_play(NULL, WINDOW_VOICE_COMBINED_ID(set_success), 0, NULL);

						g_window_ram_data.delay_unmask_card_ms = 
						gkt_systime_ms() + 1000 + 100;
						gkt_window_timer_set(TIMER_ID_CARD_DELAY_ENABLE, 
							1000, 0, 0);
					}
				}
#endif			
				else if (WINDOW_OPCODE_COMPATIBLE_RFID_STANDBY_SOFT_POWEROFF == describe) {
					if (gp_window_unreset_data->rfid_standby_mode != GKT_CARD_STANDBY_POWEROFF) {
						g_window_ram_data.delay_unmask_card = 1;
						gkt_event_mask_single(GKT_EVENT_CARD, 0);
		
						if (!key_masked) {
							gkt_thread_sleep(100);
							gkt_event_unmask_single(GKT_EVENT_KEY);
						}
						
						gp_window_unreset_data->rfid_standby_mode = GKT_CARD_STANDBY_POWEROFF;/*rfid standby soft poweroff*/
						gkt_card_standby_mode(GKT_CARD_STANDBY_POWEROFF);
						window_data_save();

						gkt_window_voice_play(NULL, WINDOW_VOICE_COMBINED_ID(set_success), 0, NULL);

						g_window_ram_data.delay_unmask_card_ms = 
						gkt_systime_ms() + 1000 + 100;
						gkt_window_timer_set(TIMER_ID_CARD_DELAY_ENABLE, 
							1000, 0, 0);
					}
					
				}			
				else if (WINDOW_OPCODE_COMPATIBLE_RFID_STANDBY_LPCD == describe) {
					if (gp_window_unreset_data->rfid_standby_mode != GKT_CARD_STANDBY_LPCD) {
						g_window_ram_data.delay_unmask_card = 1;
						gkt_event_mask_single(GKT_EVENT_CARD, 0);
		
						if (!key_masked) {
							gkt_thread_sleep(100);
							gkt_event_unmask_single(GKT_EVENT_KEY);
						}
						gp_window_unreset_data->rfid_standby_mode = GKT_CARD_STANDBY_LPCD;/*rfid standby lpcd*/
						gkt_card_standby_mode(GKT_CARD_STANDBY_LPCD);
						window_data_save();

						gkt_window_voice_play(NULL, WINDOW_VOICE_COMBINED_ID(set_success), 0, NULL);

						g_window_ram_data.delay_unmask_card_ms = 
						gkt_systime_ms() + 1000 + 100;
						gkt_window_timer_set(TIMER_ID_CARD_DELAY_ENABLE, 
							1000, 0, 0);
					}
				}
				else if (WINDOW_OPCODE_COMPATIBLE_KEYPAD_OPEN_PARAMETER_TEST_PRINT == describe) {
					g_window_ram_data.delay_unmask_card = 1;
					gkt_event_mask_single(GKT_EVENT_CARD, 0);
	
					if (!key_masked) {
						gkt_thread_sleep(100);
						gkt_event_unmask_single(GKT_EVENT_KEY);
					}

					gkt_keypad_parameter_print_open();
					gkt_window_voice_play(NULL, WINDOW_VOICE_COMBINED_ID(set_success), 0, NULL);

					g_window_ram_data.delay_unmask_card_ms = 
					gkt_systime_ms() + 1000 + 100;
					gkt_window_timer_set(TIMER_ID_CARD_DELAY_ENABLE, 
						1000, 0, 0);
				}
				else if (WINDOW_OPCODE_COMPATIBLE_KEYPAD_OPEN_REAL_TRIM_PRINT == describe) {
					g_window_ram_data.delay_unmask_card = 1;
					gkt_event_mask_single(GKT_EVENT_CARD, 0);
	
					if (!key_masked) {
						gkt_thread_sleep(100);
						gkt_event_unmask_single(GKT_EVENT_KEY);
					}

					gkt_keypad_real_trim_print_open();
					gkt_window_voice_play(NULL, WINDOW_VOICE_COMBINED_ID(set_success), 0, NULL);

					g_window_ram_data.delay_unmask_card_ms = 
					gkt_systime_ms() + 1000 + 100;
					gkt_window_timer_set(TIMER_ID_CARD_DELAY_ENABLE, 
						1000, 0, 0);
				}
#if !defined(GKT_CONFIG_DOOR_LOCK_AUTOMATIC) || !GKT_CONFIG_DOOR_LOCK_AUTOMATIC					
				else if (WINDOW_OPCODE_COMPATIBLE_MOTOR_ROTATE_DIRECTION_FORWARD == describe) {
					if (gp_window_unreset_data->lock_motor_rotate_direction != GKT_DOOR_LOCK_MOTOR_ROTATE_DIRECTION_FORWARD) {
						g_window_ram_data.delay_unmask_card = 1;
						gkt_event_mask_single(GKT_EVENT_CARD, 0);
	
						if (!key_masked) {
							gkt_thread_sleep(100);
							gkt_event_unmask_single(GKT_EVENT_KEY);
						}
					
						gp_window_unreset_data->lock_motor_rotate_direction = GKT_DOOR_LOCK_MOTOR_ROTATE_DIRECTION_FORWARD;
						gkt_door_lock_set_motor_rotate_direction(gp_window_unreset_data->lock_motor_rotate_direction);
						window_data_save();

						gkt_window_voice_play(NULL, WINDOW_VOICE_COMBINED_ID(set_success), 0, NULL);

						g_window_ram_data.delay_unmask_card_ms = 
						gkt_systime_ms() + 1000 + 100;
						gkt_window_timer_set(TIMER_ID_CARD_DELAY_ENABLE, 
							1000, 0, 0);
					}
				}
				else if (WINDOW_OPCODE_COMPATIBLE_MOTOR_ROTATE_DIRECTION_REVERSE == describe) {
					if (gp_window_unreset_data->lock_motor_rotate_direction != GKT_DOOR_LOCK_MOTOR_ROTATE_DIRECTION_REVERSE) {
						g_window_ram_data.delay_unmask_card = 1;
						gkt_event_mask_single(GKT_EVENT_CARD, 0);
	
						if (!key_masked) {
							gkt_thread_sleep(100);
							gkt_event_unmask_single(GKT_EVENT_KEY);
						}
					
						gp_window_unreset_data->lock_motor_rotate_direction = GKT_DOOR_LOCK_MOTOR_ROTATE_DIRECTION_REVERSE;
						gkt_door_lock_set_motor_rotate_direction(gp_window_unreset_data->lock_motor_rotate_direction);
						window_data_save();

						gkt_window_voice_play(NULL, WINDOW_VOICE_COMBINED_ID(set_success), 0, NULL);

						g_window_ram_data.delay_unmask_card_ms = 
						gkt_systime_ms() + 1000 + 100;
						gkt_window_timer_set(TIMER_ID_CARD_DELAY_ENABLE, 
							1000, 0, 0);
					}
				}
#endif				
				else
					goto open_verify;

				gkt_event_mask_single(GKT_EVENT_CARD, 0);
				g_window_ram_data.delay_unmask_card = 1;

				return;
			}
		}
	
open_verify:
		gkt_event_mask_single(GKT_EVENT_CARD, 0);
		s_window_welcome.verify_attr.unlock.extend_data = 
				(uint32_t)&s_window_welcome.card_info;	
	}
#endif
	gkt_window_show(WINDOW_ID_verify, 
			(uint32_t)&s_window_welcome.verify_attr);
}

#if defined(GKT_CONFIG_DOOR_TAMPER_ENABLE) && GKT_CONFIG_DOOR_TAMPER_ENABLE
#ifdef GKT_CONFIG_WINDOW_WELCOME_DOOR_TAMPER_KEY_LED_FLICKER_BITS
#define WINDOW_WELCOME_DOOR_TAMPER_KEY_LED_FLICKER_BITS	\
	GKT_CONFIG_WINDOW_WELCOME_DOOR_TAMPER_KEY_LED_FLICKER_BITS
#else
#define WINDOW_WELCOME_DOOR_TAMPER_KEY_LED_FLICKER_BITS	\
	((1U << GKT_KEY_1) | (1U << GKT_KEY_3) | (1U << GKT_KEY_5) \
		| (1U << GKT_KEY_7) | (1U << GKT_KEY_9))
#endif

static void window_welcome_door_tamper_start_check(void)
{
	int detect;

	detect = gkt_door_tamper_is_detected();
	if (gp_window_data->door_tamper_alarm_enable
		&& detect && !g_window_ram_data.door_tamper_detect) 
	{
		g_window_ram_data.door_tamper_detect = 1;
		s_window_welcome.door_tamper_poll_counter = DOOR_TAMPER_CHECK_COUNTER;
		gkt_window_timer_set(TIMER_ID_DOOR_TAMPER_CHECK,
				DOOR_TAMPER_CHECK_UNIT,
				GKT_WINDOW_TIMER_F_PERIODIC | GKT_WINDOW_TIMER_F_DETACHED,
				0);
	}
}
static void window_welcome_door_tamper_do_check(void)
{
	int detect;

	if (g_window_ram_data.door_tamper_detect
		&& s_window_welcome.door_tamper_poll_counter)
	{
		detect = gkt_door_tamper_is_detected();
		if (detect) {
			s_window_welcome.door_tamper_poll_counter--;
			if (!s_window_welcome.door_tamper_poll_counter) {
				gkt_window_timer_clear(TIMER_ID_DOOR_TAMPER_CHECK);

				gkt_window_timeout_disable("door_tamper - 1");
				window_welcome_play_voice(WINDOW_WELCOME_VOICE_DOOR_TEMPER);
				//window_common_control_key_real_trim("door_tamper", 0);
				gkt_key_led_flicker(WINDOW_WELCOME_DOOR_TAMPER_KEY_LED_FLICKER_BITS,
						GKT_KEY_LED_FLICKER_F_CYCLES_INFINITE);
				g_window_ram_data.door_tamper_alarm = 1;
			}
		}
		else {
			gkt_window_timer_clear(TIMER_ID_DOOR_TAMPER_CHECK);
			g_window_ram_data.door_tamper_detect = 0;
			s_window_welcome.door_tamper_poll_counter = 0;
		}
	}
}
static void window_welcome_door_tamper_stop(void)
{
	if (g_window_ram_data.door_tamper_detect) {
		g_window_ram_data.door_tamper_detect = 0;

		if (s_window_welcome.door_tamper_poll_counter) {
			gkt_window_timer_clear(TIMER_ID_DOOR_TAMPER_CHECK);
			s_window_welcome.door_tamper_poll_counter = 0;
		}

		if (g_window_ram_data.door_tamper_alarm) {
			g_window_ram_data.door_tamper_alarm = 0;
			gkt_key_led_flicker(0, 0);
			//window_common_control_key_real_trim("door_tamper", 1);
			window_welcome_stop_voice(WINDOW_WELCOME_VOICE_DOOR_TEMPER);
			gkt_window_timeout_enable("door_tamper - 0");
		}
	}
}
#endif

#if (defined(GKT_CONFIG_FACTORY_RESET_ENABLE) && GKT_CONFIG_FACTORY_RESET_ENABLE)
static void window_welcome_factory_reset_start_check(int type)
{
	int detect;

	detect = gkt_factory_reset_is_detected();
	if (detect && !s_window_welcome.factory_reset_detect) {
		s_window_welcome.factory_reset_detect = 1;
		s_window_welcome.factory_reset_check_complete = 0;
		s_window_welcome.factory_reset_check_complete_voice_id = -1;
		s_window_welcome.factory_reset_poll_counter = FACTORY_RESET_CHECK_COUNTER;

		gkt_window_timer_set(TIMER_ID_FACTORY_RESET_CHECK,
				FACTORY_RESET_CHECK_UNIT,
				GKT_WINDOW_TIMER_F_PERIODIC | GKT_WINDOW_TIMER_F_DETACHED,
				0);
	}
}
static void window_welcome_factory_reset_release(void)
{
	gkt_window_timer_clear(TIMER_ID_FACTORY_RESET_CHECK);

	if (s_window_welcome.factory_reset_detect) {
		s_window_welcome.factory_reset_detect = 0;

		if (s_window_welcome.factory_reset_check_complete) {
			s_window_welcome.factory_reset_check_complete = 0;

			if (s_window_welcome.factory_reset_check_complete_voice_id > 0) {
				gkt_window_voice_stop_id(s_window_welcome.factory_reset_check_complete_voice_id);
				s_window_welcome.factory_reset_check_complete_voice_id = -1;
			}
			
			gkt_window_show(WINDOW_ID_factory_reset, 1);
		}
	}
}
static void window_welcome_factory_reset_do_check(void)
{
	gkt_voice_output_playback_attr_s voice_attr;
	uint32_t remainder;
	int detect;

	if (s_window_welcome.factory_reset_detect) {
		detect = gkt_factory_reset_is_detected();
		if (detect) {
			if (!s_window_welcome.factory_reset_poll_counter)
				return;

			s_window_welcome.factory_reset_poll_counter--;
			if (s_window_welcome.factory_reset_poll_counter > 0) {
				remainder = s_window_welcome.factory_reset_poll_counter 
								% FACTORY_RESET_CHECK_COUNTER_1S;
				if (!remainder) {
					gkt_window_voice_play(NULL, WINDOW_VOICE_COMBINED_ID(key), 
							0, NULL);
				}
			}
			else if (!s_window_welcome.factory_reset_check_complete) {
				s_window_welcome.factory_reset_check_complete = 1;

				voice_attr.times = ~0;
				voice_attr.interval = 3000;
				gkt_window_voice_play(&s_window_welcome.factory_reset_check_complete_voice_id, 
						WINDOW_VOICE_COMBINED_ID(please_uplift),
						GKT_WINDOW_VOICE_F_RESIDENT | GKT_WINDOW_VOICE_F_AUTO_RESTART, 
						&voice_attr);
			}
		}
		else
			window_welcome_factory_reset_release();
	}
}
#endif

static void window_welcome_key_handle(uint32_t minor_type,uint32_t data)
{
	gkt_user_amount_s amount;

#if defined(GKT_CONFIG_RFID_ENABLE) && GKT_CONFIG_RFID_ENABLE
	if (__UNLIKELY(g_window_ram_data.delay_unmask_card))
		return;
#endif

	if ((minor_type >= GKT_KEY_0) 
		&& (minor_type <= GKT_KEY_9)) 
	{
#if !WINDOW_WELCOME_VERIFY_DISCARD_1ST_DIGIT_KEY
	#if defined (GKT_CONFIG_KEYPAD_ENABLE) && GKT_CONFIG_KEYPAD_ENABLE	
		gkt_key_stage(minor_type, data);
		window_welcome_enter_verify_window(GKT_USER_TYPE_PASSWORD, 0);
	#endif	
#else
		window_welcome_enter_verify_window(GKT_USER_TYPE_MAX, 0);
#endif
	}
	else if (GKT_KEY_BELL == minor_type)
	{
		s_window_welcome.door_bell_number = 0;	
#if defined(GKT_CONFIG_INTERNAL_DOORBELL_ENABLE) && GKT_CONFIG_INTERNAL_DOORBELL_ENABLE
		gkt_gpio_config(GKT_CONFIG_INTERNAL_DOORBELL_GPIO_PIN, GKT_GPIO_F_OUTPUT | GKT_GPIO_F_PULL_UP, NULL);
		gkt_gpio_set_pin_level(GKT_CONFIG_INTERNAL_DOORBELL_GPIO_PIN, 1);
		gkt_window_timer_set(TIMER_ID_INTERNAL_DOORBELL_DELAY, GKT_CONFIG_INTERNAL_DOORBELL_RESET_TIME_MS, 0, 0);
#endif
		window_welcome_play_voice(WINDOW_WELCOME_VOICE_DOOR_BELL);

	}
	else if (GKT_KEY_ASTERISK == minor_type) {
		gkt_user_get_amount(&amount, GKT_USER_AUTH_ADMIN, GKT_USER_TYPE_MAX);
		if (amount.used_nums) {
			/* show verify window (login main menu) */
			s_window_welcome.verify_attr.type = WINDOW_VERIFY_TYPE_LOGIN;
			s_window_welcome.verify_attr.login.action = WINDOW_VERIFY_LOGIN_ACTION_SHOW_MAIN_MENU;
			gkt_window_show(WINDOW_ID_verify, (uint32_t)&s_window_welcome.verify_attr);
		}
		else
			gkt_window_show(WINDOW_ID_initialization, 0);
	}
}
static void window_welcome_system_event_handler(
				uint32_t minor_type, uint32_t type, uint32_t data)
{
	if (GKT_WINDOW_SYSTEM_DOOR == minor_type) {
#if defined(GKT_CONFIG_DOOR_MAGNETIC_ENABLE) && GKT_CONFIG_DOOR_MAGNETIC_ENABLE
		if (GKT_DOOR_NOTIFY_MAGNETIC == type) {
			if (data)
				window_welcome_play_voice(WINDOW_WELCOME_VOICE_DOOR_NOT_CLOSED);
			else
				window_welcome_stop_voice(WINDOW_WELCOME_VOICE_DOOR_NOT_CLOSED);
			return;
		}
#endif
#if defined(GKT_CONFIG_DOOR_TAMPER_ENABLE) && GKT_CONFIG_DOOR_TAMPER_ENABLE
		if (GKT_DOOR_NOTIFY_TAMPER == type) {
			if (data)
				window_welcome_door_tamper_start_check();
			else
				window_welcome_door_tamper_stop();
			return;
		}
#endif
		gkt_unused(window_welcome_stop_voice);
	}
#if defined(GKT_CONFIG_FACTORY_RESET_ENABLE) && GKT_CONFIG_FACTORY_RESET_ENABLE
	else if (GKT_WINDOW_SYSTEM_FACTORY_RESET == minor_type) {
		if (data)
			window_welcome_factory_reset_start_check(type);
		else {
			s_window_welcome.factory_reset_check_complete = 0;
			window_welcome_factory_reset_release();
		}
	}
#endif
}

extern int	fps_capture_retval_global;
extern uint8_t g_card_calibrate_over;
static int window_welcome_event_handler(
				uint32_t major_type, uint32_t minor_type, 
				uint32_t id, uint32_t data)
{
	gkt_date_time_s new_dt;
	uint32_t i;
	
#if defined(GKT_CONFIG_RFID_ENABLE) && GKT_CONFIG_RFID_ENABLE
	if (g_window_ram_data.delay_unmask_card
		&& (g_window_ram_data.delay_unmask_card_ms > 0)) 
	{
		uint32_t time_ms = gkt_systime_ms();
		if (g_window_ram_data.delay_unmask_card_ms <= time_ms) {
			g_window_ram_data.delay_unmask_card = 0;
			g_window_ram_data.delay_unmask_card_ms = 0;

			gkt_event_unmask_single(GKT_EVENT_CARD);
		}
	}
#endif

	if (GKT_EVENT_WINDOW == major_type) {
		if (GKT_WINDOW_INIT == minor_type) {
			s_window_welcome.show_type = WINDOW_WELCOME_SHOW_MAX;

			s_window_welcome.voice_playing_id = WINDOW_WELCOME_VOICE_MAX;
			for (i = 0; i < WINDOW_WELCOME_VOICE_MAX; i++)
				s_window_welcome.voice_request_ids[i] = -1;
			
			s_window_welcome.wakeup_resource = gkt_wakeup_get_source();
			gkt_printf("window_welcome: wakeup_source = %u\n", 
					s_window_welcome.wakeup_resource);
#ifdef GKT_CONFIG_KEYPAD_SENSITIVE_STANDBY_DELTA_ATTR_TABLE
			if (gp_window_unreset_data->keypad_parameter_value == 0) {
				if (GKT_KEYPAD_PAPAMETERS == GKT_KEYPAD_PAPAMETERS_STANDARD) {
					gkt_printf("key used standard param\n");
					gp_window_unreset_data->keypad_parameter_value = GKT_KEYPAD_RESPONSE_STANDARD;
				}
				else {
					gkt_printf("key used sensitivity param\n");
					gp_window_unreset_data->keypad_parameter_value = GKT_KEYPAD_RESPONSE_SENSITIVITY;
				}

				gkt_key_parameter_update(gp_window_unreset_data->keypad_parameter_value);
				window_data_save();
			}
			else 
				gkt_key_parameter_update(gp_window_unreset_data->keypad_parameter_value);
			
#endif
#if defined(GKT_CONFIG_RFID_ENABLE) && GKT_CONFIG_RFID_ENABLE
			g_window_ram_data.delay_unmask_card = 0;
			g_window_ram_data.delay_unmask_card_ms = 0;

			if (gp_window_unreset_data->rfid_standby_mode == GKT_RFID_STANBY_NONE) {
				gp_window_unreset_data->rfid_standby_mode = RFID_STANDBY_MODE;
				window_data_save();
			}

			gkt_card_standby_mode(gp_window_unreset_data->rfid_standby_mode);
#endif
#if defined(GKT_CONFIG_DOOR_TAMPER_ENABLE) && GKT_CONFIG_DOOR_TAMPER_ENABLE
			g_window_ram_data.door_tamper_detect = 0;
			g_window_ram_data.door_tamper_alarm = 0;
#endif
			if (g_card_calibrate_over == 1)
				gkt_keypad_control(GKT_KEYPAD_CTRL_REAL_TRIM, GKT_KEYPAD_REAL_TRIM_ENABLE);
			else
				gkt_card_open_keypad_trim();
			window_welcome_get_battery_level();
		}
		else if (GKT_WINDOW_ACTIVE == minor_type) {
			uint32_t mask_type, show_type, voice_id;

			window_welcome_date_time_init();
			window_welcome_check_factory_inspect_complete();

			mask_type = WINDOW_WELCOME_MASK_DEFAULT;
			show_type = WINDOW_WELCOME_SHOW_NORMAL;
			if (data) {	/* 1st active */
				if (s_window_welcome.battery_level > GKT_BATTERY_LEVEL_EMPTY)
					voice_id = WINDOW_WELCOME_VOICE_WELCOME;
				else {
					mask_type = WINDOW_WELCOME_MASK_BATTERY_LOW;
					show_type = WINDOW_WELCOME_SHOW_BATTERY_LOW;
					voice_id = WINDOW_WELCOME_VOICE_BATTERY_LOW;
				}
				
				if (GKT_WAKEUP_SRC_keypad == s_window_welcome.wakeup_resource) {
#if defined (GKT_CONFIG_KEYPAD_ENABLE) && GKT_CONFIG_KEYPAD_ENABLE	
					if (GKT_KEY_BELL == gkt_key_wakeup()) {
						s_window_welcome.door_bell_number = 0;	
#if defined(GKT_CONFIG_INTERNAL_DOORBELL_ENABLE) && GKT_CONFIG_INTERNAL_DOORBELL_ENABLE
						gkt_gpio_config(GKT_CONFIG_INTERNAL_DOORBELL_GPIO_PIN, GKT_GPIO_F_OUTPUT | GKT_GPIO_F_PULL_UP, NULL);
						gkt_gpio_set_pin_level(GKT_CONFIG_INTERNAL_DOORBELL_GPIO_PIN, 1);
						gkt_window_timer_set(TIMER_ID_INTERNAL_DOORBELL_DELAY, GKT_CONFIG_INTERNAL_DOORBELL_RESET_TIME_MS, 0, 0);
#endif
						voice_id = WINDOW_WELCOME_VOICE_DOOR_BELL;
					}
#endif
				}
				else if (GKT_WAKEUP_SRC_fpsensor == s_window_welcome.wakeup_resource) {
					int timeout_left = 200;

					do {
						if (fps_capture_retval_global == 0) {
							window_welcome_enter_verify_window(GKT_USER_TYPE_FINGERPRINT, ~0);
							return GKT_EVENT_HANDLE_COMPLETE;
						}

						timeout_left -= 10;
						if (timeout_left < 0)
							break;
						gkt_thread_sleep(10);
					} while (1);
				}
#if defined(GKT_CONFIG_RFID_ENABLE) && GKT_CONFIG_RFID_ENABLE
				else if (GKT_WAKEUP_SRC_rfid == s_window_welcome.wakeup_resource) {
					int retval, try=20;
					uint32_t rfid_data;
					
					do {
						if (g_card_calibrate_over == 1)
							break;

						try--;
						if (try < 0)
							break;
						gkt_thread_sleep(10);
					} while(1);
					
					retval = gkt_card_get_current_info(&rfid_data);
					if (retval == GKT_SUCCESS) {
						window_welcome_enter_verify_window(GKT_USER_TYPE_CARD, (uint32_t)&rfid_data);
						return GKT_EVENT_HANDLE_COMPLETE;
					}
				}
#endif
#if (defined(GKT_CONFIG_FACTORY_RESET_ENABLE) && GKT_CONFIG_FACTORY_RESET_ENABLE)
				else if (GKT_WAKEUP_SRC_factory_reset == s_window_welcome.wakeup_resource)
					window_welcome_factory_reset_start_check(1);
#endif
#if defined(GKT_CONFIG_DOOR_TAMPER_ENABLE) && GKT_CONFIG_DOOR_TAMPER_ENABLE
				else if (GKT_WAKEUP_SRC_door_tamper == s_window_welcome.wakeup_resource)
					window_welcome_door_tamper_start_check();
#endif
			}
			else {
				voice_id = WINDOW_WELCOME_VOICE_MAX;

				if (g_window_ram_data.factory_reset_finish) {
					g_window_ram_data.factory_reset_finish = 0;
					gkt_window_show(WINDOW_ID_initialization, 0);
				}
				else if ((GKT_BATTERY_LEVEL_EMPTY == s_window_welcome.battery_level)
					&& !s_window_welcome.battery_low_showed)
				{
					mask_type = WINDOW_WELCOME_MASK_BATTERY_LOW;
					show_type = WINDOW_WELCOME_SHOW_BATTERY_LOW;
					voice_id = WINDOW_WELCOME_VOICE_BATTERY_LOW;
				}
			}

#if defined(GKT_CONFIG_FACTORY_INSPECT_ENABLE) && GKT_CONFIG_FACTORY_INSPECT_ENABLE
			if (((WINDOW_WELCOME_VOICE_MAX == voice_id)
				|| (WINDOW_WELCOME_VOICE_WELCOME == voice_id))
				&& !s_window_welcome.factory_inspect_complete) 
			{
				voice_id = WINDOW_WELCOME_VOICE_FACTORY_INSPECT_INCOMPLETE;
			}
#endif

			gkt_key_led_control(GKT_KEY_LED_CTRL_ALL_ON, 1);
			window_welcome_mask(mask_type);
			window_welcome_show(show_type);
			window_welcome_play_voice(voice_id);

		}
		else if(GKT_WINDOW_INACTIVE == minor_type) {
			s_window_welcome.wakeup_resource = GKT_WAKEUP_SRC_none;
			gkt_key_led_control(GKT_KEY_LED_CTRL_ALL_ON, 0);
		}
	}
	else if (GKT_EVENT_TIMER == major_type) {
		if (TIMER_ID_DATE_TIME_UPDATE == minor_type) {
			new_dt.date.u32_value = s_window_welcome.dt.date.u32_value;
			new_dt.time.u32_value = s_window_welcome.dt.time.u32_value;
			gkt_dt_add_seconds(&new_dt, 1);

			if (new_dt.date.u32_value != s_window_welcome.dt.date.u32_value) {
				s_window_welcome.dt.date.u32_value = new_dt.date.u32_value;
				window_welcome_update_date();
			}

			if (WINDOW_WELCOME_SHOW_NORMAL == s_window_welcome.show_type) {
				s_window_welcome.dt.time.u32_value = new_dt.time.u32_value;
				window_welcome_update_time();
			}
		}
#if defined(GKT_CONFIG_INTERNAL_DOORBELL_ENABLE) && GKT_CONFIG_INTERNAL_DOORBELL_ENABLE
		else if (TIMER_ID_INTERNAL_DOORBELL_DELAY == minor_type){
			gkt_gpio_set_pin_level(GKT_CONFIG_INTERNAL_DOORBELL_GPIO_PIN, 0);
			if (s_window_welcome.door_bell_number)
				gkt_gpio_config(GKT_CONFIG_INTERNAL_DOORBELL_GPIO_PIN, GKT_GPIO_F_INPUT | GKT_GPIO_F_PULL_DOWN, NULL);
		}
#endif
		else if(TIMER_ID_TIME_RESHOW == minor_type) {
			if (WINDOW_WELCOME_SHOW_BATTERY_LOW == s_window_welcome.show_type) {
				window_welcome_mask(WINDOW_WELCOME_MASK_DEFAULT);
				window_welcome_show(WINDOW_WELCOME_SHOW_NORMAL);
			}
		}
#if (defined(GKT_CONFIG_FACTORY_RESET_ENABLE) && GKT_CONFIG_FACTORY_RESET_ENABLE)
		else if (TIMER_ID_FACTORY_RESET_CHECK == minor_type) 
			window_welcome_factory_reset_do_check();
#endif
#if defined(GKT_CONFIG_DOOR_TAMPER_ENABLE) && GKT_CONFIG_DOOR_TAMPER_ENABLE
		else if (TIMER_ID_DOOR_TAMPER_CHECK == minor_type)
			window_welcome_door_tamper_do_check();
#endif
#if defined(GKT_CONFIG_RFID_ENABLE) && GKT_CONFIG_RFID_ENABLE
		else if (TIMER_ID_CARD_DELAY_ENABLE == minor_type) {
			g_window_ram_data.delay_unmask_card = 0;
			g_window_ram_data.delay_unmask_card_ms = 0;
			gkt_event_unmask_single(GKT_EVENT_CARD);
		}
#endif
	}
	else if (GKT_EVENT_VOICE == major_type)
		window_welcome_handle_voice_event(minor_type, (int)id);
	else if (GKT_EVENT_SYSTEM == major_type) {
		window_welcome_system_event_handler(minor_type, id, data);
	}
	else if (GKT_EVENT_KEY == major_type)
		window_welcome_key_handle(minor_type,data);
	else if (GKT_EVENT_FPS == major_type)
		window_welcome_enter_verify_window(GKT_USER_TYPE_FINGERPRINT, 0);
#if defined(GKT_CONFIG_RFID_ENABLE) && GKT_CONFIG_RFID_ENABLE
	else if (GKT_EVENT_CARD == major_type) {
		window_welcome_enter_verify_window(GKT_USER_TYPE_CARD, data);
	}
#endif

	return GKT_EVENT_HANDLE_COMPLETE;
}
GKT_WINDOW_DESC_DEFINE(welcome);

